package com.example.skillcinema.ui.screens.search.viewModels

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.example.skillcinema.adapters.FilmPagingSource
import com.example.skillcinema.db.displaymodels.FilmDisplayModel
import com.example.skillcinema.db.displaymodels.FilterForDisplay
import com.example.skillcinema.db.enums.FilmCollections
import com.example.skillcinema.db.enums.FilmOrderTypes
import com.example.skillcinema.db.enums.FilmTypes
import com.example.skillcinema.db.repositories.BaseRepository.Companion.PREVIEW_ITEMS_COUNT
import com.example.skillcinema.db.repositories.FilmRepository
import com.example.skillcinema.db.responses.FiltersCountriesResponse
import com.example.skillcinema.db.responses.FiltersGenresResponse
import com.example.skillcinema.db.responses.FiltersResponse
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class SearchViewModel @Inject constructor(val repository: FilmRepository) : ViewModel() {
    var filmType: FilmTypes = FilmTypes.ALL
    var country: FiltersCountriesResponse? = null
    var genre: FiltersGenresResponse? = null
    var year: Pair<Int, Int>? = null
    var rate: Pair<Float, Float>? = null
    var orderType: FilmOrderTypes = FilmOrderTypes.YEAR
    var isWatched: Boolean = false
    private val _searchQuery = MutableStateFlow("")
    private var searchKeyWord: String = ""
    private val _countries: MutableStateFlow<List<FilterForDisplay>> = MutableStateFlow(listOf())
    val countries = _countries.asStateFlow()
    private val _genres: MutableStateFlow<List<FilterForDisplay>> = MutableStateFlow(listOf())
    val genres = _genres.asStateFlow()
    val searchQuery: StateFlow<String> = _searchQuery.asStateFlow()
    val filmPaged: Flow<PagingData<FilmDisplayModel>> = _searchQuery.flatMapLatest {
        Pager(
            config = PagingConfig(PREVIEW_ITEMS_COUNT),
            pagingSourceFactory = { FilmPagingSource { page -> getFilmData(page) } }).flow.cachedIn(
            viewModelScope
        )
    }


    init {
        viewModelScope.launch {
            searchQuery.collectLatest {
                refreshData()
            }
        }
        viewModelScope.launch {
            val filters: FiltersResponse = repository.getFilters()
            _genres.value = filters.genres.map { it -> FilterForDisplay(it.id, it.genre) }
            _countries.value = filters.countries.map { it -> FilterForDisplay(it.id, it.country) }

        }
    }

    fun onSearchQueryChanged(query: String) {
        _searchQuery.value = query
    }

    fun refreshData() {
        searchKeyWord = _searchQuery.value
    }


    suspend fun getFilmData(page: Int): List<FilmDisplayModel> {
        val fetched: List<FilmDisplayModel> = repository.searchFilm(
            country?.id,
            genre?.id,
            orderType,
            filmType,
            rate?.first,
            rate?.second,
            year?.first,
            year?.second,
            searchKeyWord.trim(),
            page
        )

        val watched: List<FilmDisplayModel> =
            repository.db.filmCollectionCrossRefDao().getFilmsByCollectionId(3).map {
                FilmDisplayModel(
                    it.filmId,
                    it.posterUrl,
                    it.rate,
                    it.filmName,
                    it.genre,
                    FilmTypes.FILM,
                    true
                )
            }

        return if (isWatched) {
            fetched.filter { film -> watched.any { it.id == film.id } }
        } else {
            fetched
        }
    }
}
